home *** CD-ROM | disk | FTP | other *** search
/ PC Media 4 / PC MEDIA CD04.iso / share / prog / gcoope10 / funcdisp.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-07-22  |  6.2 KB  |  266 lines

  1. /*
  2.  
  3.     generic function dispatcher for GCOOPE Version 1.0
  4.     with current instance tracking via the .fext member of objFlag.
  5.  
  6.             by Brian Lee Price
  7.  
  8.         Released as Public Domain   July, 1994.
  9.  
  10. */
  11.  
  12. #include <stdarg.h>
  13. #include <stdlib.h>
  14.  
  15. #define __FUNCTION_DISPATCHER__
  16.  
  17. #include "gcstruct.h"
  18.  
  19.  
  20. /*
  21. AVAILABLE FOR EXTERNAL USE.
  22.  
  23.     This is the function dispatcher for GCOOPE, note that it actually
  24.     accesses the first parameter of the generic function's parameters.
  25.     The return function address is a function of the parameter func and
  26.     the object type parameter that is the first parm to the actual call.
  27. */
  28.  
  29. method g(generic func,...)
  30. {
  31. va_list     ap;
  32. objHndl *    instObj;
  33. boolean        update=TRUE;
  34. tag        classTag;
  35. genMethod *    gMthd;
  36. genEntry *    gEntry;
  37. char *        objDef;
  38.  
  39. va_start(ap,func);
  40. instObj=(objHndl *) ap;
  41.  
  42. /* check for the explicit call of default via. the object Object */
  43. if( *((object *) ap)==Object) goto dfltMthd;
  44.  
  45. /* test for flag class */
  46. if(*((object *) instObj)<0)
  47.     {
  48.     classTag=SIGNMASK & (instObj->fext);
  49.     update=FALSE;
  50.     }
  51. else
  52.     {
  53.     if(NULL==(objDef=getObjDef(instObj->tag))) goto err1;
  54.     objDef+=instObj->fext;
  55.     classTag=*((tag *)objDef);
  56.     if(classTag==(tag) Class)
  57.     {
  58.     classTag=instObj->tag;
  59.     update=FALSE;
  60.     }
  61.     }
  62.  
  63. /* check for class method existance */
  64. if(NULL==(gMthd = getMthd(func,classTag)))
  65.     {
  66. dfltMthd:
  67.     va_end(ap);
  68.     if(func < genTable.maxElems && func >= 0)
  69.     {
  70.     gEntry=genTable.listPtr;
  71.     gEntry+=func;
  72.     if(gEntry->defMthd!=(method) NULL)
  73.         {
  74.         return gEntry->defMthd;
  75.         }
  76.     }
  77. err1:   /* any error routes to the default method for the genFunc Err */
  78.     gEntry=genTable.listPtr;
  79.     gEntry+=(tag) Err;
  80.     return gEntry->defMthd;
  81.     }
  82. /* bypass if flag class or if a class call */
  83. if(update)
  84.     {
  85.     if(((object)NULL)==
  86.     (*((object *) ap)=steer((object) gMthd->owner,*((object *) ap))))
  87.     goto err1;
  88.     }
  89. va_end(ap);
  90. return gMthd->instMethod;
  91. }
  92.  
  93. /*
  94. AVAILABLE FOR EXTERNAL USE.
  95.  
  96.     the .fext member of structure type objHndl is used to convey the offset
  97.     within the owning instance's memory block of the current instance's
  98.     instance memory.  The macro OBJFLAG treats type object items as if
  99.     they were type objFlag.
  100.     This routine will attempt to adjust the .fext field so that the
  101.     class of the current instance will be that of the passed parm class.
  102.     If unsuccessful, NULL (cast as type object) will be returned.
  103.     Programmers Note:  the first item in an object definition memory
  104.     area is of type int and is the class tag of the instance.  This holds
  105.     true for instances offset within a child instance memory block.
  106.     Also Note: When calling an ancestor class method from within an
  107.     object method, if that ancestor class is not an immediate superClass,
  108.     the steer process can be speed up by steering it manually.  This
  109.     technique also works for inherited instance memory masked by another
  110.     inherited instance memory area of the same class located earlier in
  111.     the recursive ancestor search path.
  112. */
  113.  
  114. object steer(object class, object instance)
  115. {
  116. superEntry *    parent;
  117. char *        objPtr;
  118. classEntry *    clsEnt;
  119. tag        coi,x;
  120. object        newInst;
  121.  
  122. /* validity check */
  123. if(instance<0 || ((word) instance) > objList.maxElems)
  124.     return (object) NULL;
  125.  
  126. /* check if class of current instance is the class sought */
  127.  
  128. if(NULL==(objPtr=getObjDef((tag)instance))) return (object) NULL;
  129. objPtr+=((objHndl *) &instance)->fext;
  130. if((coi=*((tag *) objPtr)) == (tag) class) return instance;
  131.  
  132. /* immediate superClass scan */
  133.  
  134. if(NULL==(clsEnt=getObjDef(coi))) return (object) NULL;
  135. (char *) parent = &(clsEnt->cVars[clsEnt->cvSize]);
  136. for(x=clsEnt->numSuper;x>0;x--,parent++)
  137.     {
  138.     if(parent->class==(tag) class)
  139.     {
  140.     ((objHndl *) &instance)->fext+=parent->offset;
  141.     return instance;
  142.     }
  143.     }
  144.  
  145. /* recursive ancestor search */
  146. (char *) parent = &(clsEnt->cVars[clsEnt->cvSize]);
  147. for(x=clsEnt->numSuper;x>0;x--,parent++)
  148.     {
  149.     newInst=instance;
  150.     ((objHndl *) &newInst)->fext+=parent->offset;
  151.     if((object)NULL != (newInst=steer(class, newInst)))
  152.     {
  153.     return newInst;
  154.     }
  155.     }
  156. return (object) NULL;
  157. }
  158.  
  159.  
  160. /*
  161. AVAILABLE FOR EXTERNEL USE.
  162.  
  163.     Returns a pointer to the instance's memory.
  164. */
  165.  
  166. void * getIVptr(object instance)
  167. {
  168. char * retVal;
  169.  
  170. if(NULL==(retVal=getObjDef((tag) instance))) goto end;
  171. retVal+=((objHndl *) &instance)->fext + sizeof(tag);
  172. end:
  173. return retVal;
  174. }
  175.  
  176.  
  177. /*
  178. FOR KERNEL USE ONLY.
  179.  
  180.     This routine initializes an instance created when an owning
  181.     New (top-level class) calls makeInst.
  182. */
  183.  
  184. static stat initInst(tag class, tag offset, char * newObj)
  185. {
  186. classEntry *    clsEnt;
  187. superEntry *    parent;
  188. tag *        ptrA;
  189. int        x;
  190.  
  191. if((object) NULL==(clsEnt=getObjDef(class))) return FUNCFAIL;
  192. (char *) parent = &(clsEnt->cVars[clsEnt->cvSize]);
  193. ptrA =(tag *) &(newObj[offset]);
  194. *ptrA=class;
  195.  
  196. for(x=clsEnt->numSuper; x>0; x--,parent++)
  197.     {
  198.     if(initInst(parent->class,offset+parent->offset, newObj))
  199.     return FUNCFAIL;
  200.     }
  201. return FUNCOKAY;
  202. }
  203.  
  204.  
  205. /*
  206. AVAILABLE FOR EXTERNAL USE.
  207.  
  208.     This routine creates or updates/accesses an instance memory area.
  209.     It returns a pointer to the instance variable memory.
  210. */
  211.  
  212. void * makeInst(object * instPtr)
  213. {
  214. tag        class;
  215. classEntry *      clsEnt;
  216. char *        newObj=NULL;
  217.  
  218. if(((objHndl *) instPtr)->fext) return getIVptr(*instPtr);
  219.  
  220. class=((objHndl *)instPtr)->tag;
  221. if(NULL==(clsEnt=getObjDef(class))) goto end;
  222. newObj=s_calloc(1,clsEnt->totSize);
  223. *instPtr = (object) NULL;
  224. ((objHndl *) instPtr)->tag=addObject(newObj,(byte) curProcID);
  225.  
  226. if(initInst(class, 0, newObj))
  227.     {
  228.     rmvObject(((objHndl *) instPtr)->tag);
  229.     s_free(newObj);
  230.     return NULL;
  231.     }
  232. ((tag *) newObj)++;
  233. end:
  234. return newObj;
  235. }
  236.  
  237.  
  238. /*
  239. AVAILABLE FOR EXTERNAL USE.
  240.  
  241.     This routine returns a pointer to the class variable area
  242.     accessible by all members of the class.
  243. */
  244.  
  245. void * getCVptr(object class)
  246. {
  247. classEntry *     clsEnt;
  248.  
  249. if(NULL==(clsEnt=getObjDef((tag) class))) return NULL;
  250. return clsEnt->cVars;
  251. }
  252.  
  253.  
  254.  
  255. /*
  256.     This routine simply returns the passed instance
  257.  
  258. */
  259.  
  260. #pragma warn -par
  261. object bounceBack(object instance,...)
  262. {
  263. return instance;
  264. }
  265. #pragma warn +par
  266.